#include "thttpd.h"
key_t shmkey, msgkey;
int shmid, msgid;
MSG_t *shmp = NULL;
sqlite3 *db;
char *errmsg;
struct tm *tm;
time_t t;
void msg_init();
void shm_init();
void data_create();
char sql[128] = "";

static void *msg_request(void *arg)
{
    // 这里客户端描述符通过参数传进来了
    int sock = (int)arg;

    // 一般情况下，线程终止后，其终止状态一直保留到其它线程调用pthread_join获取它的状态为止。
    // 但是线程也可以被置为detach状态，这样的线程一旦终止就立刻回收它占用的所有资源，而不保留终止状态。
    pthread_detach(pthread_self());
    printf("%.2f %.2f", shmp->tem, shmp->hum);
    // handler_msg作为所有的请求处理入口
    return (void *)handler_msg(sock);
}
void write_data(int arg)
{
    if (arg == SIGALRM)
    {
        time(&t);
        tm = localtime(&t);
        memset(sql, 0, sizeof(sql));
        sprintf(sql, "insert into met values(\"%d-%d-%d %d:%d\",%.2f,%.2f);", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, shmp->tem, shmp->hum);
        if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != 0)
        {
            printf("met:%s\n", errmsg);
        }
        alarm(60);
    }
}

int main(int argc, char *argv[])
{
    msg_init();
    shm_init();
    data_create();
    // 如果不传递端口，那么使用默认端口80
    int port = 80;

    if (argc > 1)
    {
        port = atoi(argv[1]);
    }
    alarm(60);
    signal(SIGALRM, write_data);
    // 初始化服务器
    int lis_sock = init_server(port);
    while (1)
    {
        
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        int sock = accept(lis_sock, (struct sockaddr *)&peer, &len);
        if (sock < 0)
        {
            perror("accept failed");
            continue;
        }
        // 每次接收一个链接后，会自动创建一个线程，这实际上就是线程服务器模型的应用
        pthread_t tid;
        if (pthread_create(&tid, NULL, msg_request, (void *)sock) > 0)
        {
            perror("pthread_create failed");
            close(sock);
        }
    }
    return 0;
}

void shm_init()
{
    shmkey = ftok("./file", 'g');
    if (shmkey < 0)
    {
        perror("ftok err");
        return;
    }
    shmid = shmget(shmkey, 256, IPC_CREAT | IPC_EXCL | 0777);
    if (shmid < 0)
    {
        if (errno == EEXIST)
        {
            shmid = shmget(shmkey, 64, 0777);
        }
        else
        {
            perror("shmget err");
            return;
        }
    }
    shmp = (MSG_t *)shmat(shmid, NULL, 0);
    if (shmp == (MSG_t *)-1)
    {
        perror("shmat err");
        return;
    }
}

void msg_init()
{
    msgkey = ftok("./test", 'y');
    if (msgkey < 0)
    {
        perror("ftok err");
        return;
    }
    msgid = msgget(msgkey, IPC_CREAT | IPC_EXCL | 0777);
    if (msgid < 0)
    {
        if (errno == EEXIST)
        {
            msgid = msgget(msgkey, 0777);
        }
        else
        {
            perror("msgget err");
            return;
        }
    }
}

void data_create()
{
    if (sqlite3_open("./data.db", &db) != 0)
    {
        printf("sqlite3_open err:%s\n", sqlite3_errmsg(db));
        return;
    }
    printf("open data success\n");
    if (sqlite3_exec(db, "create table met(time char,tem float,hum float)", NULL, NULL, &errmsg) != 0)
    {
        printf("create met err");
        return;
    }
    printf("create met success\n");
}